"""DHCP租约管理器."""

from datetime import datetime, timedelta
from typing import List, Optional

from sqlalchemy import select, and_
from sqlalchemy.ext.asyncio import AsyncSession

from netsphere.models.dhcp import DHCPLease


class LeaseManager:
    """DHCP租约管理器."""
    
    def __init__(self, session: AsyncSession):
        """初始化租约管理器.
        
        Args:
            session: 数据库会话
        """
        self.session = session
    
    async def create_lease(
        self,
        scope_id: int,
        mac_address: str,
        ip_address: str,
        hostname: str = None,
        client_id: str = None,
        lease_time: int = 3600,
    ) -> DHCPLease:
        """创建DHCP租约.
        
        Args:
            scope_id: 作用域ID
            mac_address: MAC地址
            ip_address: IP地址
            hostname: 主机名
            client_id: 客户端ID
            lease_time: 租约时间（秒）
            
        Returns:
            DHCPLease实例
        """
        now = datetime.utcnow()
        lease = DHCPLease(
            scope_id=scope_id,
            mac_address=mac_address,
            ip_address=ip_address,
            hostname=hostname,
            client_id=client_id,
            start_time=now,
            end_time=now + timedelta(seconds=lease_time),
            renewal_time=now + timedelta(seconds=lease_time // 2),
            rebinding_time=now + timedelta(seconds=lease_time * 7 // 8),
            state="active",
        )
        self.session.add(lease)
        await self.session.commit()
        return lease
    
    async def get_active_lease_by_mac(
        self, 
        mac_address: str
    ) -> Optional[DHCPLease]:
        """根据MAC地址获取活跃租约.
        
        Args:
            mac_address: MAC地址
            
        Returns:
            DHCPLease实例或None
        """
        result = await self.session.execute(
            select(DHCPLease).where(
                and_(
                    DHCPLease.mac_address == mac_address,
                    DHCPLease.state == "active",
                    DHCPLease.end_time > datetime.utcnow()
                )
            )
        )
        return result.scalar_one_or_none()
    
    async def get_lease_by_ip(
        self, 
        ip_address: str
    ) -> Optional[DHCPLease]:
        """根据IP地址获取租约.
        
        Args:
            ip_address: IP地址
            
        Returns:
            DHCPLease实例或None
        """
        result = await self.session.execute(
            select(DHCPLease).where(
                and_(
                    DHCPLease.ip_address == ip_address,
                    DHCPLease.state == "active",
                    DHCPLease.end_time > datetime.utcnow()
                )
            )
        )
        return result.scalar_one_or_none()
    
    async def renew_lease(
        self, 
        lease_id: int, 
        new_lease_time: int = 3600
    ) -> Optional[DHCPLease]:
        """续租.
        
        Args:
            lease_id: 租约ID
            new_lease_time: 新的租约时间（秒）
            
        Returns:
            更新后的DHCPLease实例或None
        """
        lease = await self.session.get(DHCPLease, lease_id)
        if not lease or lease.state != "active":
            return None
        
        now = datetime.utcnow()
        lease.end_time = now + timedelta(seconds=new_lease_time)
        lease.renewal_time = now + timedelta(seconds=new_lease_time // 2)
        lease.rebinding_time = now + timedelta(seconds=new_lease_time * 7 // 8)
        
        self.session.add(lease)
        await self.session.commit()
        return lease
    
    async def release_lease(
        self, 
        lease_id: int
    ) -> bool:
        """释放租约.
        
        Args:
            lease_id: 租约ID
            
        Returns:
            是否成功释放
        """
        lease = await self.session.get(DHCPLease, lease_id)
        if not lease or lease.state != "active":
            return False
        
        lease.state = "released"
        self.session.add(lease)
        await self.session.commit()
        return True
    
    async def cleanup_expired_leases(self) -> int:
        """清理过期租约.
        
        Returns:
            清理的租约数量
        """
        now = datetime.utcnow()
        
        # 查找过期的活跃租约
        expired_leases = await self.session.execute(
            select(DHCPLease).where(
                and_(
                    DHCPLease.state == "active",
                    DHCPLease.end_time <= now
                )
            )
        )
        
        leases = expired_leases.scalars().all()
        count = len(leases)
        
        for lease in leases:
            lease.state = "expired"
            self.session.add(lease)
        
        if count > 0:
            await self.session.commit()
        
        return count
    
    async def list_active_leases(
        self, 
        scope_id: int = None
    ) -> List[DHCPLease]:
        """列出活跃租约.
        
        Args:
            scope_id: 作用域ID（可选）
            
        Returns:
            活跃租约列表
        """
        query = select(DHCPLease).where(
            and_(
                DHCPLease.state == "active",
                DHCPLease.end_time > datetime.utcnow()
            )
        )
        
        if scope_id is not None:
            query = query.where(DHCPLease.scope_id == scope_id)
        
        result = await self.session.execute(query)
        return list(result.scalars().all())